#include "axbopenglwidget.h"
#include <QtDebug>
// 创建 VBO VAO 对象， 并赋予 ID
unsigned int VBO, VAO, EBO;

// 去除重复的点
float vertices[] = {
    // first triangle
    0.5f, 0.5f, 0.0f, // top right
    0.5f, -0.5f, 0.0f, // bottom right
    -0.5f, -0.5f, 0.0f, // bottom left
    -0.5f, 0.5f, 0.0f // top left
};
// 添加 怎么画的 索引
unsigned int indices[] = {
    // note that we start from 0!
    0, 1, 3, // 第一个三角形
    1, 2, 3 // 第二个三角形
};


AXBOpenGLWidget::AXBOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

AXBOpenGLWidget::~AXBOpenGLWidget()
{
    makeCurrent(); // 进入当前 oepngl 状态
    glDeleteBuffers(1, &VBO); // 删除 VBO
    glDeleteBuffers(1, &EBO);  // 删除 EBO
    glDeleteVertexArrays(1, &VAO); //删除 VAO
    doneCurrent(); // 退出当前状态

}

void AXBOpenGLWidget::painShap(AXBOpenGLWidget::Shap shap)
{
    mShap = shap;
    update(); // 更新 widget;

}

void AXBOpenGLWidget::wireFrameMode(bool isWireframe)
{
    makeCurrent();
    if (isWireframe) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 默认是用 GL_FILL 填充 ，使用 GL_LINE 用线条进行填充。
    } else {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // 默认是用 GL_FILL 填充 ，使用 GL_LINE 用线条进行填充。
    }
    update();
    doneCurrent();
}

void AXBOpenGLWidget::initializeGL()
{
    // 初始化 opengl 中的函数指针
    initializeOpenGLFunctions();


    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    // 绑定 VBO 和 VAO 对象
    glBindVertexArray(VAO); // 告诉 VAO 小助理，现在开始记了
    glBindBuffer(GL_ARRAY_BUFFER, VBO); // VBO 也是一样的

    // 为当前绑定到 target 的缓冲区对象创建一个新的数据存储.（是在显存中分配缓冲）
    // 如果 data 不是 NULL, 则使用 来自此指针的数据 初始化数据存储
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 告知 显卡如何解析缓冲里的属性值 , 让 VAO 小助理，记录 如何解析缓冲中的内容
    // 第 0 个属性， 里面有三个值(x,y,z), 每个值是一个 Float类型，不需要标准化，步长为三个float 大小了， 偏移为0
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void *)0);

    // 开启 VAO 管理的第一个属性
    glEnableVertexAttribArray(0);

    // 添加 顶点着色器 代码
    int success;
    success = shaderProgram.addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Vertex, ":/shaders/shader.vert");
    if (!success) {
        qDebug() << "Error:" << shaderProgram.log();
    }

    success = shaderProgram.addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Fragment, ":/shaders/shader.frag");
    if (!success) {
        qDebug() << "Error:" << shaderProgram.log();
    }
    success = shaderProgram.link(); // 编译链接
    if (!success) {
        qDebug() << "Error:" << shaderProgram.log();
    }

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 默认是用 GL_FILL 填充 ，使用 GL_LINE 用线条进行填充。


    glGenBuffers(1, &EBO); // 创建 EBO buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 传输数据

    // 这里 EBO 中的信息，也被 VAO 小助理偷偷记录了下来

//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // 解绑 EBO
    // VAO VBO 两个助理记录完，这些信息，后让其休息 （解绑）
    glBindBuffer(GL_ARRAY_BUFFER, 0); // 解绑 VBO
    glBindVertexArray(0); // 解绑 VAO



    // VAO 都记录那些东西
    /**
    * 1. 目标是 GL_ELEMENT_ARRAY_BUFFER (EBO/IBO 索引缓冲) 的 glBindBuffer 函数调用，会被 VAO 记录下来
    * 2. 目标是 GL_ARRAY_BUFFER (VBO) 的 glBindBuffer 函数调用， VAO 不做记录。
    */
}

void AXBOpenGLWidget::resizeGL(int w, int h)
{
    Q_UNUSED(w);
    Q_UNUSED(h);
//    glViewport(0, 0, w, h);
}

void AXBOpenGLWidget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f); // 设置清理时的颜色
    glClear(GL_COLOR_BUFFER_BIT); // 使用

#if 1
    shaderProgram.bind();
#else
    glUseProgram(shaderProgram);
#endif
    switch (mShap) {
        case None:
            qDebug() << "None" << endl;
            break;
        case Rect:
            qDebug() << "绘制矩形" << endl;
            // 此时要画图了， VAO 小助理，你要再次被用
            glBindVertexArray(VAO);
        //    glDrawArrays(GL_TRIANGLES, 0, 6); // 画一个矩形 ， 这里原先是从 VBO 数组中那点的坐标的
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 /*&indices*/); // 现在是从 EBO(索引表) 中那 6 个索引， 每个索引的类型是int , 去画 三角形

            break;
        case Triangel:
            qDebug() << "绘制三角形" << endl;

            // 此时要画图了， VAO 小助理，你要再次被用
            glBindVertexArray(VAO);
        //    glDrawArrays(GL_TRIANGLES, 0, 6); // 画一个矩形 ， 这里原先是从 VBO 数组中那点的坐标的
            glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0 /*&indices*/); // 现在是从 EBO(索引表) 中那 6 个索引， 每个索引的类型是int , 去画 三角形
            break;
        default:
            qDebug() << "None" << endl;
            break;
    }
}
